home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / utils / time / tqual.c
Encoding:
C/C++ Source or Header  |  1992-08-27  |  17.7 KB  |  833 lines

  1. /*
  2.  * tqual.c --
  3.  *    POSTGRES time qualification code.
  4.  */
  5.  
  6. /* #define TQUALDEBUG    1 */
  7.  
  8. #include "tmp/postgres.h"
  9.  
  10. #include "access/htup.h"
  11. #include "access/xcxt.h"
  12. #include "access/xlog.h"
  13. #include "access/xact.h"
  14. #include "access/transam.h"
  15. #include "utils/log.h"
  16. #include "utils/nabstime.h"
  17.  
  18. #include "access/tqual.h"
  19.  
  20. RcsId("$Header: /private/postgres/src/utils/time/RCS/tqual.c,v 1.17 1992/08/07 00:43:55 mao Exp $");
  21.  
  22. /*
  23.  * TimeQualMode --
  24.  *    Mode indicator for treatment of time qualifications.
  25.  */
  26. typedef uint16    TimeQualMode;
  27.  
  28. #define TimeQualAt    0x1
  29. #define TimeQualNewer    0x2
  30. #define TimeQualOlder    0x4
  31. #define TimeQualAll    0x8
  32.  
  33. #define TimeQualMask    0xf
  34.  
  35. #define TimeQualEvery    0x0
  36. #define TimeQualRange    (TimeQualNewer | TimeQualOlder)
  37. #define TimeQualAllAt    (TimeQualAt | TimeQualAll)
  38.  
  39. typedef struct TimeQualData {
  40.     AbsoluteTime    start;
  41.     AbsoluteTime    end;
  42.     TimeQualMode    mode;
  43. } TimeQualData;
  44.  
  45. typedef TimeQualData    *InternalTimeQual;
  46.  
  47. static TimeQualData    SelfTimeQualData;
  48. TimeQual        SelfTimeQual = (Pointer)&SelfTimeQualData;
  49.  
  50. extern bool        PostgresIsInitialized;
  51.  
  52. /*
  53.  * XXX Transaction system override hacks start here
  54.  */
  55. #ifndef    GOODAMI
  56.  
  57. static TransactionId    HeapSpecialTransactionId = InvalidTransactionId;
  58. static CommandId    HeapSpecialCommandId = FirstCommandId;
  59.  
  60. void
  61. setheapoverride(on)
  62.     bool    on;
  63. {
  64.     if (on) {
  65.         TransactionIdStore(GetCurrentTransactionId(),
  66.                    &HeapSpecialTransactionId);
  67.         HeapSpecialCommandId = GetCurrentCommandId();
  68.     } else {
  69.         HeapSpecialTransactionId = InvalidTransactionId;
  70.     }
  71. }
  72.  
  73. /* static */
  74. bool
  75. heapisoverride()
  76. {
  77.     if (!TransactionIdIsValid(HeapSpecialTransactionId)) {
  78.         return (false);
  79.     }
  80.  
  81.     if (!TransactionIdEquals(GetCurrentTransactionId(),
  82.             HeapSpecialTransactionId) ||
  83.             GetCurrentCommandId() != HeapSpecialCommandId) {
  84.         HeapSpecialTransactionId = InvalidTransactionId;
  85.  
  86.         return (false);
  87.     }
  88.     return (true);
  89. }
  90.  
  91. #endif    /* !defined(GOODAMI) */
  92. /*
  93.  * XXX Transaction system override hacks end here
  94.  */
  95.  
  96. /*
  97.  * HeapTupleSatisfiesItself --
  98.  *    True iff heap tuple is valid for "itself."
  99.  *
  100.  * Note:
  101.  *    Assumes heap tuple is valid.
  102.  */
  103. static
  104. bool
  105. HeapTupleSatisfiesItself ARGS((
  106.     HeapTuple    tuple
  107. ));
  108.  
  109. /*
  110.  * HeapTupleSatisfiesNow --
  111.  *    True iff heap tuple is valid "now."
  112.  *
  113.  * Note:
  114.  *    Assumes heap tuple is valid.
  115.  */
  116. static
  117. bool
  118. HeapTupleSatisfiesNow ARGS((
  119.     HeapTuple    tuple
  120. ));
  121.  
  122. /*
  123.  * HeapTupleSatisfiesSnapshotInternalTimeQual --
  124.  *    True iff heap tuple is valid at the snapshot time qualification.
  125.  *
  126.  * Note:
  127.  *    Assumes heap tuple is valid.
  128.  *    Assumes internal time qualification is valid snapshot qualification.
  129.  */
  130. static
  131. bool
  132. HeapTupleSatisfiesSnapshotInternalTimeQual ARGS((
  133.     HeapTuple        tuple,
  134.     InternalTimeQual    qual
  135. ));
  136.  
  137. /*
  138.  * HeapTupleSatisfiesUpperBoundedInternalTimeQual --
  139.  *    True iff heap tuple is valid within a upper bounded time qualification.
  140.  *
  141.  * Note:
  142.  *    Assumes heap tuple is valid.
  143.  *    Assumes time qualification is valid ranged qualification with fixed
  144.  *    upper bound.
  145.  */
  146. static
  147. bool
  148. HeapTupleSatisfiesUpperBoundedInternalTimeQual ARGS((
  149.     HeapTuple        tuple,
  150.     InternalTimeQual    qual
  151. ));
  152.  
  153. /*
  154.  * HeapTupleSatisfiesUpperUnboundedInternalTimeQual --
  155.  *    True iff heap tuple is valid within a upper bounded time qualification.
  156.  *
  157.  * Note:
  158.  *    Assumes heap tuple is valid.
  159.  *    Assumes time qualification is valid ranged qualification with no
  160.  *    upper bound.
  161.  */
  162. static
  163. bool
  164. HeapTupleSatisfiesUpperUnboundedInternalTimeQual ARGS((
  165.     HeapTuple        tuple,
  166.     InternalTimeQual    qual
  167. ));
  168.  
  169. bool
  170. TimeQualIsValid(qual)
  171.     TimeQual    qual;
  172. {
  173.     bool    hasStartTime;
  174.  
  175.     if (!PointerIsValid(qual) || qual == SelfTimeQual) {
  176.         return (true);
  177.     }
  178.  
  179. #ifndef    GOODAMI
  180.     if (qual == LispSelfTimeQual) {
  181.         return (true);
  182.     }
  183. #endif    /* !defined(GOODAMI) */
  184.  
  185.     if (((InternalTimeQual)qual)->mode & ~TimeQualMask) {
  186.         return (false);
  187.     }
  188.  
  189.     if (((InternalTimeQual)qual)->mode & TimeQualAt) {
  190.         return (AbsoluteTimeIsValid(((InternalTimeQual)qual)->start));
  191.     }
  192.  
  193.     hasStartTime = false;
  194.  
  195.     if (((InternalTimeQual)qual)->mode & TimeQualNewer) {
  196.         if (!AbsoluteTimeIsValid(((InternalTimeQual)qual)->start)) {
  197.             return (false);
  198.         }
  199.         hasStartTime = true;
  200.     }
  201.  
  202.     if (((InternalTimeQual)qual)->mode & TimeQualOlder) {
  203.         if (!TimeIsValid(((InternalTimeQual)qual)->end)) {
  204.             return (false);
  205.         }
  206.         if (hasStartTime) {
  207.             return ((bool)!TimeIsBefore(
  208.                 ((InternalTimeQual)qual)->end,
  209.                 ((InternalTimeQual)qual)->start));
  210.         }
  211.     }
  212.     return (true);
  213. }
  214.  
  215. bool
  216. TimeQualIsLegal(qual)
  217.     TimeQual    qual;
  218. {
  219.     Assert(TimeQualIsValid(qual));
  220.  
  221.     if (qual == NowTimeQual || qual == SelfTimeQual) {
  222.         return (true);
  223.     }
  224.  
  225. #ifndef    GOODAMI
  226.     if (qual == LispSelfTimeQual) {
  227.         return (true);
  228.     }
  229. #endif    /* !defined(GOODAMI) */
  230.  
  231.     /* TimeQualAt */
  232.     if (((InternalTimeQual)qual)->mode & TimeQualAt) {
  233.         AbsoluteTime a, b;
  234.  
  235.         a = ((InternalTimeQual)qual)->start;
  236.         b = GetCurrentTransactionStartTime();
  237.  
  238.         if (AbsoluteTimeIsAfter(a, b))
  239.             return (false);
  240.         else
  241.             return (true);
  242.     }
  243.  
  244.     /* TimeQualOlder or TimeQualRange */
  245.     if (((InternalTimeQual)qual)->mode & TimeQualOlder) {
  246.         AbsoluteTime a, b;
  247.  
  248.         a = ((InternalTimeQual)qual)->end;
  249.         b = GetCurrentTransactionStartTime();
  250.  
  251.         if (AbsoluteTimeIsAfter(a, b))
  252.             return (false);
  253.         else
  254.             return (true);
  255.     }
  256.  
  257.     /* TimeQualNewer */
  258.     if (((InternalTimeQual)qual)->mode & TimeQualNewer) {
  259.         AbsoluteTime a, b;
  260.  
  261.         a = ((InternalTimeQual)qual)->start;
  262.         b = GetCurrentTransactionStartTime();
  263.  
  264.         if (AbsoluteTimeIsAfter(a, b))
  265.             return (false);
  266.         else
  267.             return (true);
  268.     }
  269.  
  270.     /* TimeQualEvery */
  271.     return (true);
  272. }
  273.  
  274. bool
  275. TimeQualIncludesNow(qual)
  276.     TimeQual    qual;
  277. {
  278.     Assert(TimeQualIsValid(qual));
  279.  
  280.     if (qual == NowTimeQual || qual == SelfTimeQual) {
  281.         return (true);
  282.     }
  283.  
  284. #ifndef    GOODAMI
  285.     if (qual == LispSelfTimeQual) {
  286.         return (false);
  287.     }
  288. #endif    /* !defined(GOODAMI) */
  289.  
  290.     if (((InternalTimeQual)qual)->mode & TimeQualAt) {
  291.         return (false);
  292.     }
  293.     if (((InternalTimeQual)qual)->mode & TimeQualOlder &&
  294.             !AbsoluteTimeIsAfter(
  295.                 ((InternalTimeQual)qual)->end,
  296.                 GetCurrentTransactionStartTime())) {
  297.  
  298.         return (false);
  299.     }
  300.     return (true);
  301. }
  302.  
  303. bool
  304. TimeQualIncludesPast(qual)
  305.     TimeQual    qual;
  306. {
  307.     Assert(TimeQualIsValid(qual));
  308.  
  309.     if (qual == NowTimeQual || qual == SelfTimeQual) {
  310.         return (false);
  311.     }
  312.  
  313. #ifndef    GOODAMI
  314.     if (qual == LispSelfTimeQual) {
  315.         return (false);
  316.     }
  317. #endif    /* !defined(GOODAMI) */
  318.  
  319.     /* otherwise, must check archive (setting locks as appropriate) */
  320.     return (true);
  321. }
  322.  
  323. bool
  324. TimeQualIsSnapshot(qual)
  325.     TimeQual    qual;
  326. {
  327.     Assert(TimeQualIsValid(qual));
  328.  
  329.     if (qual == NowTimeQual || qual == SelfTimeQual) {
  330.         return (false);
  331.     }
  332.  
  333. #ifndef    GOODAMI
  334.     if (qual == LispSelfTimeQual) {
  335.         return (false);
  336.     }
  337. #endif    /* !defined(GOODAMI) */
  338.  
  339.     return ((bool)!!(((InternalTimeQual)qual)->mode & TimeQualAt));
  340. }
  341.  
  342. bool
  343. TimeQualIsRanged(qual)
  344.     TimeQual    qual;
  345. {
  346.     Assert(TimeQualIsValid(qual));
  347.  
  348.     if (qual == NowTimeQual || qual == SelfTimeQual) {
  349.         return (false);
  350.     }
  351.  
  352. #ifndef    GOODAMI
  353.     if (qual == LispSelfTimeQual) {
  354.         return (false);
  355.     }
  356. #endif    /* !defined(GOODAMI) */
  357.  
  358.     return ((bool)!(((InternalTimeQual)qual)->mode & TimeQualAt));
  359. }
  360.  
  361. bool
  362. TimeQualIndicatesDisableValidityChecking(qual)
  363.     TimeQual    qual;
  364. {
  365.     Assert (TimeQualIsValid(qual));
  366.  
  367.     if (qual == NowTimeQual || qual == SelfTimeQual) {
  368.         return (false);
  369.     }
  370.  
  371. #ifndef    GOODAMI
  372.     if (qual == LispSelfTimeQual) {
  373.         return (false);
  374.     }
  375. #endif    /* !defined(GOODAMI) */
  376.  
  377.     if (((InternalTimeQual)qual)->mode & TimeQualAll) {
  378.         return (true);
  379.     }
  380.     return (false);
  381. }
  382.  
  383. Time
  384. TimeQualGetSnapshotTime(qual)
  385.     TimeQual    qual;
  386. {
  387.     Assert(TimeQualIsSnapshot(qual));
  388.  
  389.     return (((InternalTimeQual)qual)->start);
  390. }
  391.  
  392. Time
  393. TimeQualGetStartTime(qual)
  394.     TimeQual    qual;
  395. {
  396.     Assert(TimeQualIsRanged(qual));
  397.  
  398.     return (((InternalTimeQual)qual)->start);
  399. }
  400.  
  401. Time
  402. TimeQualGetEndTime(qual)
  403.     TimeQual    qual;
  404. {
  405.     Assert(TimeQualIsRanged(qual));
  406.  
  407.     return (((InternalTimeQual)qual)->end);
  408. }
  409.  
  410. TimeQual
  411. TimeFormSnapshotTimeQual(time)
  412.     AbsoluteTime    time;
  413. {
  414.     InternalTimeQual    qual;
  415.  
  416.     Assert(TimeIsValid(time));
  417.  
  418.     qual = LintCast(InternalTimeQual, palloc(sizeof *qual));
  419.  
  420.     qual->start = time;
  421.     qual->end = InvalidAbsoluteTime;
  422.     qual->mode = TimeQualAt;
  423.  
  424.     return ((TimeQual)qual);
  425. }
  426.  
  427. TimeQual
  428. TimeFormRangedTimeQual(startTime, endTime)
  429.     AbsoluteTime    startTime;
  430.     AbsoluteTime    endTime;
  431. {
  432.     InternalTimeQual    qual;
  433.  
  434.     qual = LintCast(InternalTimeQual, palloc(sizeof *qual));
  435.  
  436.     qual->start = startTime;
  437.     qual->end = endTime;
  438.     qual->mode = TimeQualEvery;
  439.  
  440.     if (TimeIsValid(startTime)) {
  441.         qual->mode |= TimeQualNewer;
  442.     }
  443.     if (TimeIsValid(endTime)) {
  444.         qual->mode |= TimeQualOlder;
  445.     }
  446.  
  447.     return ((TimeQual)qual);
  448. }
  449.  
  450. #if 0
  451. TimeQual
  452. TimeFormDebuggingTimeQual(time)
  453.     Time    time;
  454. {
  455.     InternalTimeQual    qual;
  456.  
  457.     Assert(TimeIsValid(time));
  458.  
  459.     qual = LintCast(InternalTimeQual, palloc(sizeof *qual));
  460.  
  461.     qual->start = time;
  462.     qual->mode = TimeQualAllAt;
  463.  
  464.     return ((TimeQual)qual);
  465. }
  466. #endif 0
  467.  
  468. /*
  469.  * Note:
  470.  *    XXX Many of the checks may be simplified and still remain correct.
  471.  *    XXX Partial answers to the checks may be cached in an ItemId.
  472.  */
  473. bool
  474. HeapTupleSatisfiesTimeQual(tuple, qual)
  475.     HeapTuple    tuple;
  476.     TimeQual    qual;
  477. {
  478.     Assert(HeapTupleIsValid(tuple));
  479.     Assert(TimeQualIsValid(qual));
  480.  
  481.     if (qual == SelfTimeQual || heapisoverride()
  482. #ifndef    GOODAMI
  483.             || qual == LispSelfTimeQual
  484. #endif    /* !defined(GOODAMI) */
  485.             ) {
  486.         return (HeapTupleSatisfiesItself(tuple));
  487.     }
  488.  
  489.     if (qual == NowTimeQual) {
  490.         return (HeapTupleSatisfiesNow(tuple));
  491.     }
  492.  
  493.     if (!TimeQualIsLegal(qual)) {
  494.         elog(WARN, "HeapTupleSatisfiesTimeQual: illegal time qual");
  495.     }
  496.  
  497.     if (TimeQualIndicatesDisableValidityChecking(qual)) {
  498.         elog(WARN, "HeapTupleSatisfiesTimeQual: no disabled validity checking (yet)");
  499.     }
  500.  
  501.     if (TimeQualIsSnapshot(qual)) {
  502.         return (HeapTupleSatisfiesSnapshotInternalTimeQual(tuple,
  503.             (InternalTimeQual)qual));
  504.     }
  505.  
  506.     if (TimeQualIncludesNow(qual)) {
  507.         return (HeapTupleSatisfiesUpperUnboundedInternalTimeQual(tuple,
  508.             (InternalTimeQual)qual));
  509.     }
  510.  
  511.     return (HeapTupleSatisfiesUpperBoundedInternalTimeQual(tuple,
  512.         (InternalTimeQual)qual));
  513. }
  514.  
  515. /*
  516.  * The satisfaction of "itself" requires the following:
  517.  *
  518.  * ((Xmin == my-transaction && (Xmax is null [|| Xmax != my-transaction)])
  519.  * ||
  520.  *
  521.  * (Xmin is committed &&
  522.  *    (Xmax is null || (Xmax != my-transaction && Xmax is not committed)))
  523.  */
  524. static
  525. bool
  526. HeapTupleSatisfiesItself(tuple)
  527.     HeapTuple    tuple;
  528. {
  529.     /*
  530.      * XXX Several evil casts are made in this routine.  Casting XID to be 
  531.      * TransactionId works only because TransactionId->data is the first
  532.      * (and only) field of the structure.
  533.      */
  534.     if (!AbsoluteTimeIsValid(tuple->t_tmin)) {
  535.     if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) &&
  536.         !TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
  537.             return (true);
  538.     }
  539.  
  540.     if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
  541.             return (false);
  542.     }
  543.     }
  544.     /* the tuple was inserted validly */
  545.  
  546.     if (AbsoluteTimeIsReal(tuple->t_tmax)) {
  547.     return (false);
  548.     }
  549.  
  550.     if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
  551.     return (true);
  552.     }
  553.  
  554.     if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
  555.     return (false);
  556.     }
  557.  
  558.     return ((bool)!TransactionIdDidCommit((TransactionId)tuple->t_xmax));
  559. }
  560.  
  561. /*
  562.  * The satisfaction of "now" requires the following:
  563.  *
  564.  * ((Xmin == my-transaction && Cmin != my-command &&
  565.  *    (Xmax is null || (Xmax == my-transaction && Cmax != my-command)))
  566.  * ||
  567.  *
  568.  * (Xmin is committed &&
  569.  *    (Xmax is null || (Xmax == my-transaction && Cmax == my-command) ||
  570.  *        (Xmax is not committed && Xmax != my-transaction))))
  571.  */
  572. static
  573. bool
  574. HeapTupleSatisfiesNow(tuple)
  575.     HeapTuple    tuple;
  576. {
  577.     AbsoluteTime curtime;
  578.  
  579.     if (AMI_OVERRIDE)
  580.     return true;
  581.     /*
  582.      *  If the transaction system isn't yet initialized, then we assume
  583.      *  that transactions committed.  We only look at system catalogs
  584.      *  during startup, so this is less awful than it seems, but it's
  585.      *  still pretty awful.
  586.      */
  587.  
  588.     if (!PostgresIsInitialized)
  589.     return ((bool)(TransactionIdIsValid((TransactionId)tuple->t_xmin) &&
  590.                !TransactionIdIsValid((TransactionId)tuple->t_xmax)));
  591.  
  592.     /*
  593.      * XXX Several evil casts are made in this routine.  Casting XID to be 
  594.      * TransactionId works only because TransactionId->data is the first
  595.      * (and only) field of the structure.
  596.      */
  597.     if (!AbsoluteTimeIsValid(tuple->t_tmin)) {
  598.  
  599.     if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin)
  600.         && CommandIdIsCurrentCommandId(tuple->t_cmin)) {
  601.  
  602.         return (false);
  603.     }
  604.  
  605.     if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin)
  606.         && !CommandIdIsCurrentCommandId(tuple->t_cmin)) {
  607.  
  608.         if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
  609.         return (true);
  610.         }
  611.  
  612.         Assert(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax));
  613.  
  614.         if (CommandIdIsCurrentCommandId(tuple->t_cmax)) {
  615.         return (true);
  616.         }
  617.     }
  618.  
  619.     /*
  620.      * this call is VERY expensive - requires a log table lookup.
  621.      */
  622.  
  623.     if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
  624.         return (false);
  625.     }
  626.  
  627.     tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin);
  628.     }
  629.  
  630.     curtime = GetCurrentTransactionStartTime();
  631.  
  632.     if (AbsoluteTimeIsAfter(tuple->t_tmin, curtime)) {
  633.     return (false);
  634.     }
  635.  
  636.     /* we can see the insert */
  637.     if (AbsoluteTimeIsReal(tuple->t_tmax)) {
  638.     if (AbsoluteTimeIsAfter(tuple->t_tmax, curtime))
  639.         return (true);
  640.  
  641.     return (false);
  642.     }
  643.  
  644.     if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
  645.     return (true);
  646.     }
  647.  
  648.     if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
  649.     return (false);
  650.     }
  651.  
  652.     if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
  653.     return (true);
  654.     }
  655.  
  656.     tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax);
  657.  
  658.     if (AbsoluteTimeIsAfter(tuple->t_tmax, curtime))
  659.     return (true);
  660.  
  661.     return (false);
  662. }
  663.  
  664. /*
  665.  * The satisfaction of Rel[T] requires the following:
  666.  *
  667.  * (Xmin is committed && Tmin <= T &&
  668.  *    (Xmax is null || (Xmax is not committed && Xmax != my-transaction) ||
  669.  *        Tmax >= T))
  670.  */
  671. static
  672. bool
  673. HeapTupleSatisfiesSnapshotInternalTimeQual(tuple, qual)
  674.     HeapTuple        tuple;
  675.     InternalTimeQual    qual;
  676. {
  677.     /*
  678.      * XXX Several evil casts are made in this routine.  Casting XID to be 
  679.      * TransactionId works only because TransactionId->data is the first
  680.      * (and only) field of the structure.
  681.      */
  682.     if (!AbsoluteTimeIsValid(tuple->t_tmin)) {
  683.  
  684.     if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
  685.         return (false);
  686.     }
  687.  
  688.     tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin);
  689.     }
  690.  
  691.     if (TimeIsBefore(TimeQualGetSnapshotTime((TimeQual)qual), tuple->t_tmin)) {
  692.     return (false);
  693.     }
  694.     /* the tuple was inserted validly before the snapshot time */
  695.  
  696.     if (!AbsoluteTimeIsReal(tuple->t_tmax)) {
  697.  
  698.     if (!TransactionIdIsValid((TransactionId)tuple->t_xmax) ||
  699.         !TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
  700.  
  701.         return (true);
  702.     }
  703.  
  704.     tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax);
  705.     }
  706.  
  707.     return ((bool)
  708.     AbsoluteTimeIsAfter(tuple->t_tmax,
  709.                 TimeQualGetSnapshotTime((TimeQual)qual)));
  710. }
  711.  
  712. /*
  713.  * The satisfaction of [T1,T2] requires the following:
  714.  *
  715.  * (Xmin is committed && Tmin <= T2 &&
  716.  *    (Xmax is null || (Xmax is not committed && Xmax != my-transaction) ||
  717.  *        T1 is null || Tmax >= T1))
  718.  */
  719. static
  720. bool
  721. HeapTupleSatisfiesUpperBoundedInternalTimeQual(tuple, qual)
  722.     HeapTuple        tuple;
  723.     InternalTimeQual    qual;
  724. {
  725.     /*
  726.      * XXX Several evil casts are made in this routine.  Casting XID to be 
  727.      * TransactionId works only because TransactionId->data is the first
  728.      * (and only) field of the structure.
  729.      */
  730.     if (!AbsoluteTimeIsValid(tuple->t_tmin)) {
  731.  
  732.     if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
  733.         return (false);
  734.     }
  735.  
  736.     tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin);
  737.     }
  738.  
  739.     if (TimeIsBefore(TimeQualGetEndTime((TimeQual)qual), tuple->t_tmin)) {
  740.     return (false);
  741.     }
  742.     /* the tuple was inserted validly before the range end */
  743.  
  744.     if (!AbsoluteTimeIsValid(TimeQualGetStartTime((TimeQual)qual))) {
  745.     return (true);
  746.     }
  747.  
  748.     if (!AbsoluteTimeIsReal(tuple->t_tmax)) {
  749.  
  750.     if (!TransactionIdIsValid((TransactionId)tuple->t_xmax) ||
  751.         !TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
  752.  
  753.         return (true);
  754.     }
  755.  
  756.     tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax);
  757.     }
  758.  
  759.     return ((bool)AbsoluteTimeIsAfter(tuple->t_tmax,
  760.                       TimeQualGetStartTime((TimeQual)qual)));
  761. }
  762.  
  763. /*
  764.  * The satisfaction of [T1,] requires the following:
  765.  *
  766.  * ((Xmin == my-transaction && Cmin != my-command &&
  767.  *    (Xmax is null || (Xmax == my-transaction && Cmax != my-command)))
  768.  * ||
  769.  *
  770.  * (Xmin is committed &&
  771.  *    (Xmax is null || (Xmax == my-transaction && Cmax == my-command) ||
  772.  *        (Xmax is not committed && Xmax != my-transaction) ||
  773.  *        T1 is null || Tmax >= T1)))
  774.  */
  775. static
  776. bool
  777. HeapTupleSatisfiesUpperUnboundedInternalTimeQual(tuple, qual)
  778.     HeapTuple        tuple;
  779.     InternalTimeQual    qual;
  780. {
  781.     if (!AbsoluteTimeIsValid(tuple->t_tmin)) {
  782.  
  783.     if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) &&
  784.         CommandIdIsCurrentCommandId(tuple->t_cmin)) {
  785.  
  786.         return (false);
  787.     }
  788.  
  789.     if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmin) &&
  790.         !CommandIdIsCurrentCommandId(tuple->t_cmin)) {
  791.  
  792.         if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
  793.         return (true);
  794.         }
  795.  
  796.         Assert(TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax));
  797.  
  798.         return ((bool) !CommandIdIsCurrentCommandId(tuple->t_cmax));
  799.     }
  800.  
  801.     if (!TransactionIdDidCommit((TransactionId)tuple->t_xmin)) {
  802.         return (false);
  803.     }
  804.  
  805.     tuple->t_tmin = TransactionIdGetCommitTime(tuple->t_xmin);
  806.     }
  807.     /* the tuple was inserted validly */
  808.  
  809.     if (!AbsoluteTimeIsValid(TimeQualGetStartTime((TimeQual)qual))) {
  810.     return (true);
  811.     }
  812.  
  813.     if (!AbsoluteTimeIsReal(tuple->t_tmax)) {
  814.  
  815.     if (!TransactionIdIsValid((TransactionId)tuple->t_xmax)) {
  816.         return (true);
  817.     }
  818.  
  819.     if (TransactionIdIsCurrentTransactionId((TransactionId)tuple->t_xmax)) {
  820.         return (CommandIdIsCurrentCommandId(tuple->t_cmin));
  821.     }
  822.  
  823.     if (!TransactionIdDidCommit((TransactionId)tuple->t_xmax)) {
  824.         return (true);
  825.     }
  826.  
  827.     tuple->t_tmax = TransactionIdGetCommitTime(tuple->t_xmax);
  828.     }
  829.  
  830.     return ((bool)AbsoluteTimeIsAfter(tuple->t_tmax,
  831.                       TimeQualGetStartTime((TimeQual)qual)));
  832. }
  833.